Main question: at this point we’re interested in one single classification, i.e. what predicts whether people do maskless contacts with non-householders

Research Document

Questions codebook

Method of delivery

sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Big Sur 10.16

Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] parallel  stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] catboost_0.26       rpart_4.1-15        rattle_5.4.0        bitops_1.0-7        tibble_3.1.2        doParallel_1.0.16   iterators_1.0.13    foreach_1.5.1      
 [9] cvms_1.3.0          tidyr_1.1.3         randomForest_4.6-14 caret_6.0-88        lattice_0.20-41     DataExplorer_0.8.2  faux_1.0.0          dplyr_1.0.7        
[17] magrittr_2.0.1      parsnip_0.1.6       ggplot2_3.3.4      

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.6           lubridate_1.7.10     class_7.3-17         assertthat_0.2.1     digest_0.6.27        ipred_0.9-11         utf8_1.2.1           R6_2.5.0            
 [9] plyr_1.8.6           stats4_4.0.3         evaluate_0.14        pillar_1.6.1         tictoc_1.0.1         rlang_0.4.11         data.table_1.14.0    Matrix_1.2-18       
[17] rmarkdown_2.5        splines_4.0.3        gower_0.2.2          stringr_1.4.0        htmlwidgets_1.5.2    igraph_1.2.6         munsell_0.5.0        compiler_4.0.3      
[25] xfun_0.19            pkgconfig_2.0.3      htmltools_0.5.0      nnet_7.3-14          tidyselect_1.1.1     gridExtra_2.3        prodlim_2019.11.13   codetools_0.2-16    
[33] fansi_0.5.0          crayon_1.4.1         withr_2.4.2          MASS_7.3-53          recipes_0.1.16       ModelMetrics_1.2.2.2 grid_4.0.3           jsonlite_1.7.2      
[41] nlme_3.1-149         gtable_0.3.0         lifecycle_1.0.0      DBI_1.1.1            pROC_1.17.0.1        scales_1.1.1         stringi_1.6.2        reshape2_1.4.4      
[49] timeDate_3043.102    ellipsis_0.3.2       generics_0.1.0       vctrs_0.3.8          lava_1.6.9           tools_4.0.3          glue_1.4.2           purrr_0.3.4         
[57] networkD3_0.4        survival_3.2-7       colorspace_2.0-1     knitr_1.30          
df <- read.csv("data/shield_gjames_21-06-10.csv")
grouping_var <- "behaviour_unmasked"
# feature_list <- colnames(df[, !(names(df) %in% c(grouping_var, "id"))])
# feature_list <- c('intention_indoor_meeting', 'norms_people_present_indoors',
#        'sdt_motivation_extrinsic_2', 'sdt_motivation_identified_4', 'norms_family_friends', 'norms_risk_groups', 'norms_officials',
#        'norms_people_present_indoors')
if (grouping_var == "behaviour_unmasked") {
  # df <- df %>% mutate(tmp = if_else(!!as.symbol(grouping_var) != 5, 'bad', 'good'))
  df <- df %>% mutate(tmp = if_else(!!as.symbol(grouping_var) != 5, 0, 1))

  names(df)[names(df) == 'tmp'] <- paste0(grouping_var, "_bool")
}
    
df[, paste0(grouping_var, "_bool")] <- as.factor(df[, paste0(grouping_var, "_bool")])
# df %<>%
#        mutate_each_(funs(factor(.)), colnames(df))
# str(df)

ordinal_vars_mydata <- ordering_lookup %>% 
  dplyr::filter(varname %in% names(df)) %>% 
  dplyr::filter(ordering == "ordered")
  
df <- df %>% 
  # Ordered variables as ordinal factors
  dplyr::mutate(across(.cols = ordinal_vars_mydata$varname, 
                        ~factor(., ordered = TRUE))) %>% 
  # Everything else as unordered factors
  dplyr::mutate(across(.cols = -ordinal_vars_mydata$varname, 
                        ~factor(.))) %>% 
  # Fix ordering in the intention variables
  dplyr::mutate(across(.cols = contains("intention_"), 
                        ~dplyr::recode_factor(.,
                                              "1" = "4",
                                              "2" = "1", 
                                              "3" = "2",
                                              "4" = "3",
                                              .ordered = TRUE)))

str(df)
'data.frame':   2272 obs. of  94 variables:
 $ id                               : Factor w/ 2272 levels "1","2","3","4",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ demographic_gender               : Factor w/ 2 levels "1","2": 1 2 1 1 1 2 2 2 1 1 ...
 $ demographic_age                  : Ord.factor w/ 5 levels "18-29"<"30-39"<..: 4 2 1 5 5 4 1 2 5 5 ...
 $ demographic_4_areas              : Factor w/ 4 levels "1","2","3","4": 1 2 1 1 2 1 1 4 4 1 ...
 $ demographic_8_areas              : Factor w/ 8 levels "1","2","3","4",..: 2 6 2 2 7 1 2 6 6 7 ...
 $ behaviour_indoors_nonhouseholders: Ord.factor w/ 6 levels "1"<"2"<"3"<"4"<..: 5 5 3 4 5 3 5 5 4 5 ...
 $ behaviour_close_contact          : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 4 4 2 3 4 3 4 4 4 3 ...
 $ behaviour_quarantined            : Factor w/ 3 levels "1","2","3": 2 2 2 2 2 2 2 2 2 2 ...
 $ behaviour_unmasked               : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 5 5 2 2 4 3 5 3 4 5 ...
 $ mask_wearing_cloth_mask          : Factor w/ 2 levels "0","1": 1 2 1 1 1 1 2 1 1 1 ...
 $ mask_wearing_disposable_mask     : Factor w/ 2 levels "0","1": 2 2 2 1 2 1 1 2 1 1 ...
 $ mask_wearing_certified_mask      : Factor w/ 2 levels "0","1": 1 1 1 1 1 2 1 1 2 1 ...
 $ mask_wearing_ffp2                : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 2 ...
 $ mask_wearing_vizire              : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ mask_wearing_none                : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ mask_wearing_other               : Factor w/ 2 levels "0","1": 1 1 1 2 1 1 1 1 1 1 ...
 $ mask_wearing_reuse               : Factor w/ 5 levels "1","2","3","4",..: 2 4 2 5 3 2 5 4 2 4 ...
 $ intention_store                  : Ord.factor w/ 4 levels "4"<"1"<"2"<"3": 1 1 1 1 1 1 1 3 1 1 ...
 $ intention_public_transport       : Ord.factor w/ 4 levels "4"<"1"<"2"<"3": 4 1 1 1 1 1 1 4 1 1 ...
 $ intention_indoor_meeting         : Ord.factor w/ 4 levels "4"<"1"<"2"<"3": 1 3 3 2 2 3 3 3 2 1 ...
 $ intention_restaurant             : Ord.factor w/ 4 levels "4"<"1"<"2"<"3": 2 2 2 2 1 1 2 3 1 2 ...
 $ intention_pa                     : Ord.factor w/ 4 levels "4"<"1"<"2"<"3": 2 2 4 4 3 2 4 3 2 4 ...
 $ automaticity_carry_mask          : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 6 3 5 6 7 6 7 1 5 6 ...
 $ automaticity_put_on_mask         : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 4 6 6 6 7 7 7 1 6 6 ...
 $ post_covid_maskwearing_if_reccd  : Factor w/ 4 levels "1","2","3","4": 3 4 4 3 1 1 4 4 1 1 ...
 $ inst_attitude_protects_self      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 6 4 4 4 6 7 4 4 6 ...
 $ inst_attitude_protects_others    : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 6 7 7 6 7 6 7 4 6 6 ...
 $ inst_attitude_sense_of_community : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 4 4 4 6 7 4 7 1 5 6 ...
 $ inst_attitude_enough_oxygen      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 3 7 6 7 4 7 1 5 3 ...
 $ inst_attitude_no_needless_waste  : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 3 1 7 6 7 4 7 1 5 1 ...
 $ norms_family_friends             : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 6 7 7 6 7 7 7 1 4 7 ...
 $ norms_risk_groups                : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 5 7 4 6 7 7 7 2 7 7 ...
 $ norms_officials                  : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 7 7 7 6 7 7 7 7 7 7 ...
 $ norms_people_present_indoors     : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 5 7 7 6 7 4 7 4 6 7 ...
 $ aff_attitude_comfortable         : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 4 5 5 3 4 6 1 5 2 ...
 $ aff_attitude_calm                : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 4 3 7 6 7 5 6 3 6 3 ...
 $ aff_attitude_safe                : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 3 4 5 5 4 5 7 5 6 5 ...
 $ aff_attitude_responsible         : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 6 6 7 5 7 6 7 4 7 6 ...
 $ aff_attitude_difficult_breathing : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 4 1 3 2 5 2 6 5 5 ...
 $ barriers_nothing                 : Factor w/ 2 levels "0","1": 1 1 1 1 2 1 2 1 1 1 ...
 $ barriers_money                   : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ barriers_forget_carry            : Factor w/ 2 levels "0","1": 1 2 2 2 1 1 1 1 2 1 ...
 $ barriers_forget_wear             : Factor w/ 2 levels "0","1": 1 1 1 2 1 1 1 1 2 1 ...
 $ barriers_group_pressure          : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ barriers_medical_symptoms        : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ barriers_skin                    : Factor w/ 2 levels "0","1": 1 2 1 1 1 1 1 1 1 1 ...
 $ barriers_difficult_breathing     : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 2 1 2 ...
 $ barriers_eyeglasses_fog          : Factor w/ 2 levels "0","1": 1 2 2 2 1 2 1 2 1 2 ...
 $ barriers_raspyvoice              : Factor w/ 2 levels "0","1": 2 1 1 2 1 1 1 2 1 1 ...
 $ barriers_headache                : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ barriers_drymouth                : Factor w/ 2 levels "0","1": 1 1 1 1 1 2 1 1 1 1 ...
 $ barriers_earpain                 : Factor w/ 2 levels "0","1": 1 2 1 1 1 2 1 1 1 1 ...
 $ barriers_general_uncomfy         : Factor w/ 2 levels "0","1": 2 1 1 1 1 1 1 2 1 2 ...
 $ barriers_other                   : Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
 $ effective_means_handwashing      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 6 1 7 5 7 6 7 7 7 7 ...
 $ effective_means_masks            : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 5 5 1 5 7 6 6 1 7 7 ...
 $ effective_means_distance         : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 7 4 1 7 7 5 5 7 7 7 ...
 $ effective_means_ventilation      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 7 4 4 7 7 5 5 4 6 7 ...
 $ risk_likely_contagion            : Ord.factor w/ 8 levels "1"<"2"<"3"<"4"<..: 2 4 4 3 2 2 2 3 3 1 ...
 $ risk_contagion_absent_protection : Ord.factor w/ 8 levels "1"<"2"<"3"<"4"<..: 6 5 6 5 6 5 6 3 6 4 ...
 $ risk_severity                    : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 6 2 5 6 4 5 3 1 4 7 ...
 $ risk_fear_spread                 : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 4 5 7 4 6 5 7 4 3 7 ...
 $ risk_fear_contagion_self         : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 7 3 5 6 4 5 3 3 4 7 ...
 $ risk_fear_contagion_others       : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 7 7 6 6 7 6 7 7 4 7 ...
 $ risk_fear_restrictions           : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 5 3 1 3 1 4 1 7 3 4 ...
 $ sdt_needs_autonomy_1             : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 2 3 5 3 5 2 5 2 4 2 ...
 $ sdt_needs_competence_1           : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 3 4 5 4 5 4 5 4 4 3 ...
 $ sdt_needs_relatedness_1          : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 3 5 1 4 5 4 5 1 5 4 ...
 $ sdt_needs_autonomy_2             : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 2 4 2 3 5 4 5 1 4 4 ...
 $ sdt_needs_competence_2           : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 3 5 5 2 4 4 5 3 4 3 ...
 $ sdt_needs_relatedness_2          : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 3 2 4 3 5 4 5 2 5 4 ...
 $ sdt_motivation_extrinsic1        : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 6 1 1 2 1 2 2 1 4 1 ...
 $ sdt_motivation_amotivation_1     : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 1 1 1 2 1 1 1 5 2 1 ...
 $ sdt_motivation_identified_1      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 7 7 5 6 7 6 7 4 7 7 ...
 $ sdt_motivation_introjected_1     : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 5 5 1 3 6 3 5 1 6 6 ...
 $ sdt_motivation_extrinsic_2       : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 4 1 2 2 4 1 5 2 1 ...
 $ sdt_motivation_introjected_2     : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 5 1 5 6 5 7 1 6 4 ...
 $ sdt_motivation_amotivation_2     : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 1 1 1 1 1 2 1 5 1 1 ...
 $ sdt_motivation_extrinsic_3       : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 1 2 1 4 1 5 1 6 2 1 ...
 $ sdt_motivation_identified_2      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 3 7 3 6 7 5 7 1 6 6 ...
 $ sdt_motivation_identified_3      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 6 7 2 6 7 5 7 1 7 6 ...
 $ sdt_motivation_identified_4      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 4 7 4 5 7 5 7 1 6 6 ...
 $ sdt_motivation_amotivation_3     : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 1 1 2 1 1 1 6 1 1 ...
 $ sdt_motivation_introjected_3     : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 7 3 5 6 5 5 4 6 6 ...
 $ attention_check                  : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 1 1 2 1 1 1 1 1 1 ...
 $ vaccination_status_intention_self: Ord.factor w/ 5 levels "4"<"1"<"2"<"3"<..: 1 2 3 1 1 1 3 4 1 2 ...
 $ vaccination_status_closeones     : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 1 2 1 2 4 2 3 2 4 4 ...
 $ covid_tested                     : Factor w/ 4 levels "1","2","3","4": 1 3 2 2 3 1 2 2 2 2 ...
 $ had_covid                        : Ord.factor w/ 5 levels "1"<"2"<"3"<"4"<..: 1 2 5 2 1 1 4 1 2 1 ...
 $ demographic_risk_group           : Factor w/ 3 levels "1","2","3": 2 2 2 1 2 2 2 2 2 3 ...
 $ needprotection_before_shots      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 1 1 1 2 1 1 1 4 1 1 ...
 $ needprotection_after_1_shot      : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 2 2 1 2 1 2 1 4 1 1 ...
 $ needprotection_after_2_shots     : Ord.factor w/ 7 levels "1"<"2"<"3"<"4"<..: 3 5 7 2 3 3 3 4 1 1 ...
 $ behaviour_unmasked_bool          : Factor w/ 2 levels "0","1": 2 2 1 1 1 1 2 1 1 2 ...
# Exploratory data analysis
plot_intro(df)

plot_bar(df)
1 columns ignored with more than 50 categories.
id: 2272 categories

plot_correlation(df)
1 features with more than 20 categories ignored!
id: 2272 categories

head(df[, c(paste0(grouping_var, "_bool"), grouping_var)])
x <- df %>%
  select(-behaviour_unmasked_bool, -behaviour_unmasked, -id) %>%
  as.data.frame()

y <- df$behaviour_unmasked_bool
set.seed(2021)
inTrain <- createDataPartition(y, p = .80, list = FALSE)[,1]

x_train <- x[ inTrain, ]
x_test  <- x[-inTrain, ]

y_train <- y[ inTrain]
y_test  <- y[-inTrain]

colnames(x_train)
 [1] "demographic_gender"                "demographic_age"                   "demographic_4_areas"               "demographic_8_areas"              
 [5] "behaviour_indoors_nonhouseholders" "behaviour_close_contact"           "behaviour_quarantined"             "mask_wearing_cloth_mask"          
 [9] "mask_wearing_disposable_mask"      "mask_wearing_certified_mask"       "mask_wearing_ffp2"                 "mask_wearing_vizire"              
[13] "mask_wearing_none"                 "mask_wearing_other"                "mask_wearing_reuse"                "intention_store"                  
[17] "intention_public_transport"        "intention_indoor_meeting"          "intention_restaurant"              "intention_pa"                     
[21] "automaticity_carry_mask"           "automaticity_put_on_mask"          "post_covid_maskwearing_if_reccd"   "inst_attitude_protects_self"      
[25] "inst_attitude_protects_others"     "inst_attitude_sense_of_community"  "inst_attitude_enough_oxygen"       "inst_attitude_no_needless_waste"  
[29] "norms_family_friends"              "norms_risk_groups"                 "norms_officials"                   "norms_people_present_indoors"     
[33] "aff_attitude_comfortable"          "aff_attitude_calm"                 "aff_attitude_safe"                 "aff_attitude_responsible"         
[37] "aff_attitude_difficult_breathing"  "barriers_nothing"                  "barriers_money"                    "barriers_forget_carry"            
[41] "barriers_forget_wear"              "barriers_group_pressure"           "barriers_medical_symptoms"         "barriers_skin"                    
[45] "barriers_difficult_breathing"      "barriers_eyeglasses_fog"           "barriers_raspyvoice"               "barriers_headache"                
[49] "barriers_drymouth"                 "barriers_earpain"                  "barriers_general_uncomfy"          "barriers_other"                   
[53] "effective_means_handwashing"       "effective_means_masks"             "effective_means_distance"          "effective_means_ventilation"      
[57] "risk_likely_contagion"             "risk_contagion_absent_protection"  "risk_severity"                     "risk_fear_spread"                 
[61] "risk_fear_contagion_self"          "risk_fear_contagion_others"        "risk_fear_restrictions"            "sdt_needs_autonomy_1"             
[65] "sdt_needs_competence_1"            "sdt_needs_relatedness_1"           "sdt_needs_autonomy_2"              "sdt_needs_competence_2"           
[69] "sdt_needs_relatedness_2"           "sdt_motivation_extrinsic1"         "sdt_motivation_amotivation_1"      "sdt_motivation_identified_1"      
[73] "sdt_motivation_introjected_1"      "sdt_motivation_extrinsic_2"        "sdt_motivation_introjected_2"      "sdt_motivation_amotivation_2"     
[77] "sdt_motivation_extrinsic_3"        "sdt_motivation_identified_2"       "sdt_motivation_identified_3"       "sdt_motivation_identified_4"      
[81] "sdt_motivation_amotivation_3"      "sdt_motivation_introjected_3"      "attention_check"                   "vaccination_status_intention_self"
[85] "vaccination_status_closeones"      "covid_tested"                      "had_covid"                         "demographic_risk_group"           
[89] "needprotection_before_shots"       "needprotection_after_1_shot"       "needprotection_after_2_shots"     
fit_control <- trainControl(method = "repeatedcv",
                            number = 10, #10
                        repeats=10, #10
                            classProbs = TRUE)
grid <- expand.grid(depth = c(4, 6, 8),
                    learning_rate = 0.1,
                    iterations = 50, #500
                    l2_leaf_reg = 1e-3,
                    rsm = 0.95,
                    border_count = 64)
tictoc::tic()
cl <- makePSOCKcluster(10)
registerDoParallel(cl)

set.seed(69420)

report <- train(x, as.factor(make.names(y)),
                method = catboost.caret,
                logging_level = 'Silent', #'Verbose', 
                preProc = NULL,
                tuneGrid = grid, trControl = fit_control)

stopCluster(cl)
tictoc::toc()
71.571 sec elapsed
registerDoSEQ()
report
Catboost 

2272 samples
  91 predictor
   2 classes: 'X0', 'X1' 

No pre-processing
Resampling: Cross-Validated (10 fold, repeated 10 times) 
Summary of sample sizes: 2044, 2045, 2045, 2045, 2044, 2045, ... 
Resampling results across tuning parameters:

  depth  Accuracy   Kappa    
  4      0.7309843  0.4188090
  6      0.7237668  0.4048342
  8      0.7173828  0.3900885

Tuning parameter 'learning_rate' was held constant at a value of 0.1
Tuning parameter 'iterations' was held constant at a value of 50
Tuning parameter 'l2_leaf_reg'
 was held constant at a value of 0.001
Tuning parameter 'rsm' was held constant at a value of 0.95
Tuning parameter 'border_count' was held constant at a value of 64
Accuracy was used to select the optimal model using the largest value.
The final values used for the model were depth = 4, learning_rate = 0.1, iterations = 50, l2_leaf_reg = 0.001, rsm = 0.95 and border_count = 64.
report$results
importance <- varImp(report, scale = FALSE)
importance
custom variable importance

  only 20 most important variables shown (out of 91)
x_pool <- catboost.load_pool(x)

model <- report$finalModel
model
CatBoost model (50 trees)
Loss function: Logloss
Fit to 91 features
shap_values <- catboost.get_feature_importance(
  model,
  pool = x_pool,
  type = "ShapValues",
  thread_count = -1,
  fstr_type = NULL
)
shap_values_df <- data.frame(shap_values[, 1:ncol(x)])
colnames(shap_values_df) <- colnames(x)

shap_values_df_melt <- reshape2::melt(shap_values_df, value.name="shap_value")
No id variables; using all as measure variables
tmp_x <- data.frame(sapply(x, as.numeric))

actual_values_df_melt <- reshape2::melt(tmp_x, value.name="actual_value")
No id variables; using all as measure variables
shap_actual_df <- cbind(actual_values_df_melt, shap_values_df_melt["shap_value"])
# shap_actual_df[c("actual_value", "shap_value")] <- sapply(shap_actual_df[c("actual_value", "shap_value")], as.factor)

shap_actual_df[c("actual_value")] <- sapply(shap_actual_df[c("actual_value")], as.factor)
ggplot(shap_actual_df, aes(x=shap_value, y=variable, color=actual_value)) + 
  geom_jitter()

stop!
Error: unexpected '!' in "stop!"
LS0tCnRpdGxlOiAiQ29yb25hIHByZXBwaW5nIHVzaW5nIEZpbm5pc2ggZGF0YSBEZWNpc2lvbiBUcmVlcyIKYXV0aG9yOiAiSmFtZXMgVHdvc2UiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCk1haW4gcXVlc3Rpb246IGF0IHRoaXMgcG9pbnQgd2UncmUgaW50ZXJlc3RlZCBpbiBvbmUgc2luZ2xlIGNsYXNzaWZpY2F0aW9uLCBpLmUuIHdoYXQgcHJlZGljdHMgd2hldGhlciBwZW9wbGUgZG8gbWFza2xlc3MgY29udGFjdHMgd2l0aCBub24taG91c2Vob2xkZXJzCgpbUmVzZWFyY2ggRG9jdW1lbnRdKGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL2RvY3VtZW50L2QvMWlMY2lIY3ZWdmY4UXdGUzd3aXlOQmV2cEQxQjl5RFJxTWxNNF9vQ2NWY0EvZWRpdD91c3A9c2hhcmluZykKCltRdWVzdGlvbnMgY29kZWJvb2tdKGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL2RvY3VtZW50L2QvMVlaVkNQMVVOeG5OTEFLMmtZRGZBOVk5OGxlVFpZdXJaRC1kOGlCeWhkaTAvZWRpdD91c3A9c2hhcmluZykKCltNZXRob2Qgb2YgZGVsaXZlcnldKGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL2RvY3VtZW50L2QvMUcxSlQ5SlVKclRLM2FhWFh1UmF3WUFDSmFHTnhVN21jWEw5aS1kOGVLWFkvZWRpdCkKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGFyc25pcCkKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShkcGx5cikKbGlicmFyeShmYXV4KQpsaWJyYXJ5KERhdGFFeHBsb3JlcikKbGlicmFyeShjYXJldCkKbGlicmFyeShyYW5kb21Gb3Jlc3QpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoY3ZtcykKbGlicmFyeShkb1BhcmFsbGVsKQpsaWJyYXJ5KHJhdHRsZSkKbGlicmFyeShycGFydCkKc291cmNlKCJjb3JvbmFwcmVwcGVyc19leHRyYXMuUiIpCiMgZGV2dG9vbHM6Omluc3RhbGxfdXJsKCdodHRwczovL2dpdGh1Yi5jb20vY2F0Ym9vc3QvY2F0Ym9vc3QvcmVsZWFzZXMvZG93bmxvYWQvdjAuMjYvY2F0Ym9vc3QtUi1EYXJ3aW4tMC4yNi50Z3onKQpsaWJyYXJ5KGNhdGJvb3N0KQoKIyBpbnN0YWwgc2hhcHBlcgojIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiTW9kZWxPcmllbnRlZC9zaGFwcGVyIikKCiMgaW5zdGFsbCBzaGFwIHB5dGhvbiBsaWJyYXJ5CiMgc2hhcHBlcjo6aW5zdGFsbF9zaGFwKCkKCmBgYAoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCgoKYGBge3J9CmRmIDwtIHJlYWQuY3N2KCJkYXRhL3NoaWVsZF9namFtZXNfMjEtMDYtMTAuY3N2IikKYGBgCgpgYGB7cn0KZ3JvdXBpbmdfdmFyIDwtICJiZWhhdmlvdXJfdW5tYXNrZWQiCiMgZmVhdHVyZV9saXN0IDwtIGNvbG5hbWVzKGRmWywgIShuYW1lcyhkZikgJWluJSBjKGdyb3VwaW5nX3ZhciwgImlkIikpXSkKIyBmZWF0dXJlX2xpc3QgPC0gYygnaW50ZW50aW9uX2luZG9vcl9tZWV0aW5nJywgJ25vcm1zX3Blb3BsZV9wcmVzZW50X2luZG9vcnMnLAojICAgICAgICAnc2R0X21vdGl2YXRpb25fZXh0cmluc2ljXzInLCAnc2R0X21vdGl2YXRpb25faWRlbnRpZmllZF80JywgJ25vcm1zX2ZhbWlseV9mcmllbmRzJywgJ25vcm1zX3Jpc2tfZ3JvdXBzJywgJ25vcm1zX29mZmljaWFscycsCiMgICAgICAgICdub3Jtc19wZW9wbGVfcHJlc2VudF9pbmRvb3JzJykKYGBgCgpgYGB7cn0KaWYgKGdyb3VwaW5nX3ZhciA9PSAiYmVoYXZpb3VyX3VubWFza2VkIikgewogICMgZGYgPC0gZGYgJT4lIG11dGF0ZSh0bXAgPSBpZl9lbHNlKCEhYXMuc3ltYm9sKGdyb3VwaW5nX3ZhcikgIT0gNSwgJ2JhZCcsICdnb29kJykpCiAgZGYgPC0gZGYgJT4lIG11dGF0ZSh0bXAgPSBpZl9lbHNlKCEhYXMuc3ltYm9sKGdyb3VwaW5nX3ZhcikgIT0gNSwgMCwgMSkpCgogIG5hbWVzKGRmKVtuYW1lcyhkZikgPT0gJ3RtcCddIDwtIHBhc3RlMChncm91cGluZ192YXIsICJfYm9vbCIpCn0KICAgIApgYGAKCmBgYHtyfQpkZlssIHBhc3RlMChncm91cGluZ192YXIsICJfYm9vbCIpXSA8LSBhcy5mYWN0b3IoZGZbLCBwYXN0ZTAoZ3JvdXBpbmdfdmFyLCAiX2Jvb2wiKV0pCmBgYAoKYGBge3J9CiMgZGYgJTw+JQojICAgICAgICBtdXRhdGVfZWFjaF8oZnVucyhmYWN0b3IoLikpLCBjb2xuYW1lcyhkZikpCiMgc3RyKGRmKQoKb3JkaW5hbF92YXJzX215ZGF0YSA8LSBvcmRlcmluZ19sb29rdXAgJT4lIAogIGRwbHlyOjpmaWx0ZXIodmFybmFtZSAlaW4lIG5hbWVzKGRmKSkgJT4lIAogIGRwbHlyOjpmaWx0ZXIob3JkZXJpbmcgPT0gIm9yZGVyZWQiKQogIApkZiA8LSBkZiAlPiUgCiAgIyBPcmRlcmVkIHZhcmlhYmxlcyBhcyBvcmRpbmFsIGZhY3RvcnMKICBkcGx5cjo6bXV0YXRlKGFjcm9zcyguY29scyA9IG9yZGluYWxfdmFyc19teWRhdGEkdmFybmFtZSwgCiAgICAgICAgICAgICAgICAgICAgICAgIH5mYWN0b3IoLiwgb3JkZXJlZCA9IFRSVUUpKSkgJT4lIAogICMgRXZlcnl0aGluZyBlbHNlIGFzIHVub3JkZXJlZCBmYWN0b3JzCiAgZHBseXI6Om11dGF0ZShhY3Jvc3MoLmNvbHMgPSAtb3JkaW5hbF92YXJzX215ZGF0YSR2YXJuYW1lLCAKICAgICAgICAgICAgICAgICAgICAgICAgfmZhY3RvciguKSkpICU+JSAKICAjIEZpeCBvcmRlcmluZyBpbiB0aGUgaW50ZW50aW9uIHZhcmlhYmxlcwogIGRwbHlyOjptdXRhdGUoYWNyb3NzKC5jb2xzID0gY29udGFpbnMoImludGVudGlvbl8iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIH5kcGx5cjo6cmVjb2RlX2ZhY3RvciguLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjEiID0gIjQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjIiID0gIjEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIzIiA9ICIyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI0IiA9ICIzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5vcmRlcmVkID0gVFJVRSkpKQoKc3RyKGRmKQoKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD0xNSwgZmlnLndpZHRoPTE1fQojIEV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMKcGxvdF9pbnRybyhkZikKcGxvdF9iYXIoZGYpCnBsb3RfY29ycmVsYXRpb24oZGYpCmBgYAoKCmBgYHtyfQpoZWFkKGRmWywgYyhwYXN0ZTAoZ3JvdXBpbmdfdmFyLCAiX2Jvb2wiKSwgZ3JvdXBpbmdfdmFyKV0pCmBgYAoKYGBge3J9CnggPC0gZGYgJT4lCiAgc2VsZWN0KC1iZWhhdmlvdXJfdW5tYXNrZWRfYm9vbCwgLWJlaGF2aW91cl91bm1hc2tlZCwgLWlkKSAlPiUKICBhcy5kYXRhLmZyYW1lKCkKCnkgPC0gZGYkYmVoYXZpb3VyX3VubWFza2VkX2Jvb2wKYGBgCgoKYGBge3J9CnNldC5zZWVkKDIwMjEpCmluVHJhaW4gPC0gY3JlYXRlRGF0YVBhcnRpdGlvbih5LCBwID0gLjgwLCBsaXN0ID0gRkFMU0UpWywxXQoKeF90cmFpbiA8LSB4WyBpblRyYWluLCBdCnhfdGVzdCAgPC0geFstaW5UcmFpbiwgXQoKeV90cmFpbiA8LSB5WyBpblRyYWluXQp5X3Rlc3QgIDwtIHlbLWluVHJhaW5dCgpjb2xuYW1lcyh4X3RyYWluKQpgYGAKCgpgYGB7cn0KZml0X2NvbnRyb2wgPC0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJyZXBlYXRlZGN2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bWJlciA9IDEwLCAjMTAKICAgICAgICAgICAgICAgICAgICAgICAgcmVwZWF0cz0xMCwgIzEwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzc1Byb2JzID0gVFJVRSkKYGBgCgoKYGBge3J9CmdyaWQgPC0gZXhwYW5kLmdyaWQoZGVwdGggPSBjKDQsIDYsIDgpLAogICAgICAgICAgICAgICAgICAgIGxlYXJuaW5nX3JhdGUgPSAwLjEsCiAgICAgICAgICAgICAgICAgICAgaXRlcmF0aW9ucyA9IDUwLCAjNTAwCiAgICAgICAgICAgICAgICAgICAgbDJfbGVhZl9yZWcgPSAxZS0zLAogICAgICAgICAgICAgICAgICAgIHJzbSA9IDAuOTUsCiAgICAgICAgICAgICAgICAgICAgYm9yZGVyX2NvdW50ID0gNjQpCmBgYAoKCmBgYHtyfQp0aWN0b2M6OnRpYygpCmNsIDwtIG1ha2VQU09DS2NsdXN0ZXIoMTApCnJlZ2lzdGVyRG9QYXJhbGxlbChjbCkKCnNldC5zZWVkKDY5NDIwKQoKcmVwb3J0IDwtIHRyYWluKHgsIGFzLmZhY3RvcihtYWtlLm5hbWVzKHkpKSwKICAgICAgICAgICAgICAgIG1ldGhvZCA9IGNhdGJvb3N0LmNhcmV0LAogICAgICAgICAgICAgICAgbG9nZ2luZ19sZXZlbCA9ICdTaWxlbnQnLCAjJ1ZlcmJvc2UnLCAKICAgICAgICAgICAgICAgIHByZVByb2MgPSBOVUxMLAogICAgICAgICAgICAgICAgdHVuZUdyaWQgPSBncmlkLCB0ckNvbnRyb2wgPSBmaXRfY29udHJvbCkKCnN0b3BDbHVzdGVyKGNsKQp0aWN0b2M6OnRvYygpCmBgYAoKYGBge3J9CnJlZ2lzdGVyRG9TRVEoKQpgYGAKCmBgYHtyfQpyZXBvcnQKYGBgCgpgYGB7cn0KcmVwb3J0JHJlc3VsdHMKYGBgCgoKYGBge3J9CmltcG9ydGFuY2UgPC0gdmFySW1wKHJlcG9ydCwgc2NhbGUgPSBGQUxTRSkKaW1wb3J0YW5jZQpgYGAKCmBgYHtyfQp4X3Bvb2wgPC0gY2F0Ym9vc3QubG9hZF9wb29sKHgpCgptb2RlbCA8LSByZXBvcnQkZmluYWxNb2RlbAptb2RlbApgYGAKCmBgYHtyfQpzaGFwX3ZhbHVlcyA8LSBjYXRib29zdC5nZXRfZmVhdHVyZV9pbXBvcnRhbmNlKAogIG1vZGVsLAogIHBvb2wgPSB4X3Bvb2wsCiAgdHlwZSA9ICJTaGFwVmFsdWVzIiwKICB0aHJlYWRfY291bnQgPSAtMSwKICBmc3RyX3R5cGUgPSBOVUxMCikKYGBgCgoKYGBge3J9CnNoYXBfdmFsdWVzX2RmIDwtIGRhdGEuZnJhbWUoc2hhcF92YWx1ZXNbLCAxOm5jb2woeCldKQpjb2xuYW1lcyhzaGFwX3ZhbHVlc19kZikgPC0gY29sbmFtZXMoeCkKCnNoYXBfdmFsdWVzX2RmX21lbHQgPC0gcmVzaGFwZTI6Om1lbHQoc2hhcF92YWx1ZXNfZGYsIHZhbHVlLm5hbWU9InNoYXBfdmFsdWUiKQoKdG1wX3ggPC0gZGF0YS5mcmFtZShzYXBwbHkoeCwgYXMubnVtZXJpYykpCgphY3R1YWxfdmFsdWVzX2RmX21lbHQgPC0gcmVzaGFwZTI6Om1lbHQodG1wX3gsIHZhbHVlLm5hbWU9ImFjdHVhbF92YWx1ZSIpCgpzaGFwX2FjdHVhbF9kZiA8LSBjYmluZChhY3R1YWxfdmFsdWVzX2RmX21lbHQsIHNoYXBfdmFsdWVzX2RmX21lbHRbInNoYXBfdmFsdWUiXSkKYGBgCgpgYGB7cn0KIyBzaGFwX2FjdHVhbF9kZltjKCJhY3R1YWxfdmFsdWUiLCAic2hhcF92YWx1ZSIpXSA8LSBzYXBwbHkoc2hhcF9hY3R1YWxfZGZbYygiYWN0dWFsX3ZhbHVlIiwgInNoYXBfdmFsdWUiKV0sIGFzLmZhY3RvcikKCnNoYXBfYWN0dWFsX2RmW2MoImFjdHVhbF92YWx1ZSIpXSA8LSBzYXBwbHkoc2hhcF9hY3R1YWxfZGZbYygiYWN0dWFsX3ZhbHVlIildLCBhcy5mYWN0b3IpCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTE1fQpnZ3Bsb3Qoc2hhcF9hY3R1YWxfZGYsIGFlcyh4PXNoYXBfdmFsdWUsIHk9dmFyaWFibGUsIGNvbG9yPWFjdHVhbF92YWx1ZSkpICsgCiAgZ2VvbV9qaXR0ZXIoKQpgYGAKCgpgYGB7cn0Kc3RvcCEKYGBgCgoKCmBgYHtyfQojIFBvc3QgcHJlZGljdGlvbgpwb3N0UmVzYW1wbGUocHJlZGljdChkZWNfbW9kLCB4X3Rlc3QpLCB5X3Rlc3QpCmBgYAoKCmBgYHtyfQpwcmVkaWN0aW9uX3RpYmJsZSA8LSB0aWJibGUoInRhcmdldCI9eV90ZXN0LAogICAgICAgInByZWRpY3Rpb24iPXByZWRpY3QoZGVjX21vZCwgeF90ZXN0KSkKcHJlZGljdGlvbl90YWJsZSA8LSB0YWJsZShwcmVkaWN0aW9uX3RpYmJsZSkKY2ZtIDwtIGFzX3RpYmJsZShwcmVkaWN0aW9uX3RhYmxlKQpwbG90X2NvbmZ1c2lvbl9tYXRyaXgoY2ZtLCAKICAgICAgICAgICAgICAgICAgICAgIHRhcmdldF9jb2wgPSAidGFyZ2V0IiwgCiAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0aW9uX2NvbCA9ICJwcmVkaWN0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgIGNvdW50c19jb2wgPSAibiIpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xNX0KZmFuY3lScGFydFBsb3QoZGVjX21vZCRmaW5hbE1vZGVsKQpgYGAKCgpgYGB7cn0KcHJlZF9kZiA8LSBkYXRhLmZyYW1lKHRhcmdldD1hcy5udW1lcmljKHlfdGVzdCksCiAgICAgICAgICAgcHJlZGljdGlvbj1hcy5udW1lcmljKHByZWRpY3QoZGVjX21vZCwgeF90ZXN0KSksCiAgICAgICAgICAgcm93Lm5hbWVzID0gcm93bmFtZXMoeF90ZXN0KSkKCnByZWRfZGYkY29ycmVjdF9vcl9ub3QgPC0gcHJlZF9kZiR0YXJnZXQgKyBwcmVkX2RmJHByZWRpY3Rpb24KCnplcm9faWRzIDwtIHJvd25hbWVzKHByZWRfZGZbcHJlZF9kZlssICJjb3JyZWN0X29yX25vdCJdID09IDIsXSkKb25lX2lkcyA8LSByb3duYW1lcyhwcmVkX2RmW3ByZWRfZGZbLCAiY29ycmVjdF9vcl9ub3QiXSA9PSA0LF0pCgpsZW5ndGgoemVyb19pZHMpCmxlbmd0aChvbmVfaWRzKQpgYGAKCmBgYHtyfQpkZlt6ZXJvX2lkcywgXQpkZltvbmVfaWRzLCBdCmBgYAoKYGBge3J9CnRvcF9mZWF0dXJlcyA8LSByb3duYW1lcyhoZWFkKHZhcmltcF9kYXRhJGltcG9ydGFuY2UsIDMpKQojIHRvcF9mZWF0dXJlcyA8LSBjKCJiZWhhdmlvdXJfaW5kb29yc19ub25ob3VzZWhvbGRlcnMiLCAiYmVoYXZpb3VyX2Nsb3NlX2NvbnRhY3QiLCAiaW50ZW50aW9uX2luZG9vcl9tZWV0aW5nIikKYGBgCgpgYGB7cn0KIyBkZiRkZW1vZ3JhcGhpY19nZW5kZXIgPC0gZmFjdG9yKGRmJGRlbW9ncmFwaGljX2dlbmRlcikKIyBkZiA8LSBkYXRhLmZyYW1lKGFwcGx5KGRmLCAyLCBmYWN0b3IpKQpgYGAKCmBgYHtyfQojIGRmICU8PiUKIyAgICAgICAgbXV0YXRlX2VhY2hfKGZ1bnMoZmFjdG9yKC4pKSx0b3BfZmVhdHVyZXMpCiMgIyBzdHIoZGYpCmBgYAoKCmBgYHtyfQp4IDwtIGRmW3RvcF9mZWF0dXJlc10KCnkgPC0gZmFjdG9yKGRmJGJlaGF2aW91cl91bm1hc2tlZF9ib29sKQoKYGBgCgpgYGB7cn0Kc2V0LnNlZWQoMjAyMSkKaW5UcmFpbiA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKHksIHAgPSAuODAsIGxpc3QgPSBGQUxTRSlbLDFdCgp4X3RyYWluIDwtIHhbIGluVHJhaW4sIF0KeF90ZXN0ICA8LSB4Wy1pblRyYWluLCBdCgp5X3RyYWluIDwtIHlbIGluVHJhaW5dCnlfdGVzdCAgPC0geVstaW5UcmFpbl0KCmNvbG5hbWVzKHhfdHJhaW4pCmBgYAoKYGBge3J9CmNsIDwtIG1ha2VQU09DS2NsdXN0ZXIoMTApCnJlZ2lzdGVyRG9QYXJhbGxlbChjbCkKCnNldC5zZWVkKDIwMjEpCgojIFNwZWNpZnkgMTAgZm9sZCBjcm9zcy12YWxpZGF0aW9uCmN0cmxfY3YgPC0gdHJhaW5Db250cm9sKG1ldGhvZCA9ICJyZXBlYXRlZGN2IiwKICAgICAgICAgICAgICAgICAgICAgICAgc2VhcmNoPSJncmlkIiwKICAgICAgICAgICAgICAgICAgICAgICAgbnVtYmVyID0gMTAsCiAgICAgICAgICAgICAgICAgICAgICAgIHJlcGVhdHM9MTAsCiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWluZ1NhbXBzID0gNSwKICAgICAgICAgICAgICAgICAgICAgICAgIyBzZWVkcyA9IGMoMToxMDEpCiAgICAgICAgICAgICAgICAgICAgICAgICkKIyBQcmVkaWN0IGluY29tZSB1c2luZyBkZWNpc2lvbiB0cmVlCmRlY19tb2QgPC0gdHJhaW4oeD14X3RyYWluLAogICAgICAgICAgICAgICAgIHk9eV90cmFpbiwKICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAicnBhcnRTY29yZSIsICAKICAgICAgICAgICAgICAgICAgICB0ckNvbnRyb2wgPSBjdHJsX2N2LAogICAgICAgICAgICAgICAgICAgIHR1bmVHcmlkID0gZXhwYW5kLmdyaWQoCiAgICAgICAgICAgICAgICAgICAgICBjcCA9IHNlcSgwLDEsMC4xKSwKICAgICAgICAgICAgICAgICAgICAgIHNwbGl0ID0gYygiYWJzIiwgInF1YWQiKSwKICAgICAgICAgICAgICAgICAgICAgIHBydW5lID0gYygibWMiLCAibXIiKQogICAgICAgICAgICAgICAgICAgICAgKQoKICAgICAgICAgICAgICAgICApCgpzdG9wQ2x1c3RlcihjbCkKYGBgCgpgYGB7cn0KcmVnaXN0ZXJEb1NFUSgpCmBgYAoKYGBge3J9CiMgUG9zdCBwcmVkaWN0aW9uCnBvc3RSZXNhbXBsZShwcmVkaWN0KGRlY19tb2QsIHhfdGVzdCksIHlfdGVzdCkKYGBgCgpgYGB7cn0KcHJlZGljdGlvbl90aWJibGUgPC0gdGliYmxlKCJ0YXJnZXQiPXlfdGVzdCwKICAgICAgICJwcmVkaWN0aW9uIj1wcmVkaWN0KGRlY19tb2QsIHhfdGVzdCkpCnByZWRpY3Rpb25fdGFibGUgPC0gdGFibGUocHJlZGljdGlvbl90aWJibGUpCmNmbSA8LSBhc190aWJibGUocHJlZGljdGlvbl90YWJsZSkKCmBgYAoKCmBgYHtyfQpwbG90X2NvbmZ1c2lvbl9tYXRyaXgoY2ZtLCAKICAgICAgICAgICAgICAgICAgICAgIHRhcmdldF9jb2wgPSAidGFyZ2V0IiwgCiAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0aW9uX2NvbCA9ICJwcmVkaWN0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgIGNvdW50c19jb2wgPSAibiIpCiAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgIApgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTV9CmZhbmN5UnBhcnRQbG90KGRlY19tb2QkZmluYWxNb2RlbCkKYGBgCgoKYGBge3J9CnZhckltcChkZWNfbW9kKQpgYGAKCgpgYGB7cn0KZ2dwbG90KGRhdGE9ZGYsIGFlcyh4PWlkLCB5PWludGVudGlvbl9zdG9yZSwgY29sb3I9ZGVtb2dyYXBoaWNfZ2VuZGVyKSkgKyBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGE9ZGYsIGFlcyh4PWlkLCB5PWJlaGF2aW91cl9pbmRvb3JzX25vbmhvdXNlaG9sZGVycywgY29sb3I9ZGVtb2dyYXBoaWNfZ2VuZGVyKSkgKyBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KZGVjX21vZApgYGAKCmBgYHtyfQpkZWNfbW9kJGJlc3RUdW5lCmRlY19tb2QkZmluYWxNb2RlbApgYGAKCg==